package wumpus;

import java.io.*;


public class WumpusGame {

	private boolean hasAnArrow = true;
    private boolean hasTheGold = false;
	private final Board cave;
	private int direction;
	private Cell currentCell;
	private int currentX, currentY;
	private int score;
	
	public WumpusGame() {
		cave = new Board();
		this.setCurrentCell(cave.getCell(0, 0));
		this.setCurrentX(0);
		this.setCurrentY(0);
		this.setDirection(1);
		this.setScore(0);
		this.setHasAnArrow(true);
	}
	public void setScore(int i) {
		this.score = i;
	}
	public void addScore(int amount){
		this.score += amount;
	}
	public int getScore(){
		return this.score;
	}
	public void setHasTheGold(boolean hasTheGold) {
		this.hasTheGold = hasTheGold;
	}
	public boolean hasTheGold() {
		return hasTheGold;
	}
	public void setCurrentY(int currentY) {
		if(this.cave.isYValid(currentY))
		    this.currentY = currentY;
	}
	public int getCurrentY() {
		return currentY;
	}
	public void setCurrentX(int currentX) {
		if(this.cave.isXValid(currentX))
		    this.currentX = currentX;
	}
	public int getCurrentX() {
		return currentX;
	}
	public void setCurrentCell(Cell currentCell) {
		this.currentCell = currentCell;
	}
	public Cell getCurrentCell() {
		return currentCell;
	}
	public void setDirection(int direction) {
		this.direction = direction;
	}
	public int getDirection() {
		return direction;
	}
	public Board getCave() {
		return cave;
	}
	public void setHasAnArrow(boolean hasAnArrow) {
		this.hasAnArrow = hasAnArrow;
	}
	public boolean hasAnArrow() {
		return hasAnArrow;
	}

	public void play() {
		this.currentCell.printCell();
		while(true) {
			if(this.hasTheGold()){ 
				System.out.println("You won! Your score: " + this.getScore());
				break;
			}
			if (this.currentCell.hasHole()) {
				this.addScore(-1000);
				System.out.println("You fell into a hole! Your score: " + this.getScore());
				break;
			}
			if(this.currentCell.hasWumpus() && this.currentCell.isWumpusAlive()) {
				this.addScore(-1000);
				System.out.println("Wumpus ATE you! Your score: " + this.getScore());
				break;
			}
			
			analyze(askPlayer("Give me a command"));
		}
	}
	
	/**
	 * Use this to ask new command from player
	 * @return the answer from the player
	 */
	public String askPlayer(String question) {
		System.out.println(question + " > ");
		BufferedReader e = new BufferedReader(new InputStreamReader(System.in));
		String userCommand = "";
		try{
		   userCommand = e.readLine();
		} catch (IOException ex) {
			System.err.println(ex.getMessage());
			
		}
		return userCommand;
	}
	
	public boolean turn(StringTokenizer st) {
		String word = null;
		if(st.hasMoreTokens()) { word = st.nextToken().toLowerCase();}
		int wS = -1;
		while(true) {
			wS = WumpusConstants.getDirectionInt(word);
		    
			switch(wS) {
		        case 0: case 4: this.setDirection(0); break;
		        case 1: case 5: this.setDirection(1); break;
		        case 2: case 6: this.setDirection(2); break;
		        case 3: case 7: this.setDirection(3); break;
		        case -1: default:
		        	String s = this.askPlayer("Sorry, I couldn't unerstand. Do you want to turn? (Yes/No)").toLowerCase();
		        	if(s.startsWith("n")) return false;
		        	word = this.askPlayer("Ok, so where were you going again?"); 
		        	continue;
		    }
			System.out.println("You're now going " + WumpusConstants.directionsLC[this.getDirection()]);
			this.addScore(-1);
		    break;
		}
		return true;
	}
	
	public int shoot(StringTokenizer st) {
		if(!this.hasAnArrow) {
			System.out.println("You have already used your only arrow!");
			this.addScore(-1);
			return 0;
		}
		
		String word = null;
		if(st.hasMoreTokens()) { word = st.nextToken().toLowerCase();}
		int wS = -1;
		while(true) {
			wS = WumpusConstants.getDirectionInt(word);
		    
			switch(wS) {
		        case 0: case 4: case 8: case 12: 
		        	this.setDirection(0); cave.performShoot(getCurrentX(), getCurrentY(), 0); break;
		        case 1: case 5: case 9: case 13:
		        	this.setDirection(1); cave.performShoot(getCurrentX(), getCurrentY(), 1); break;
		        case 2: case 6: case 10: case 14:
		        	this.setDirection(2); cave.performShoot(getCurrentX(), getCurrentY(), 2); break;
		        case 3: case 7: case 11: case 15:
		        	this.setDirection(3); cave.performShoot(getCurrentX(), getCurrentY(), 3); break;
		        case -1: default:
		        	String s = this.askPlayer("Do you want to shoot to current direction "+
		        			WumpusConstants.directionsLC[this.getDirection()]+"? (Yes/No)").toLowerCase();
		        	if(s.startsWith("n")) {
		        		System.out.println("You put your arrow back...");
		        		return 0;
		        	}
		        	word = WumpusConstants.directionsLC[this.getDirection()];
		        	continue;
		    }
			System.out.println("You shot! Did you hear a scream?");
			this.addScore(-10);
			this.setHasAnArrow(false);
		    break;
		}
		return 0;
	}
	 
	
	public boolean move(StringTokenizer st ) {
		String word = null;
		if(st.hasMoreTokens()) { word = st.nextToken().toLowerCase();}
		int wS = -1;
		if (this.currentCell != null) {
			this.cave.removeScream();
			this.currentCell.setHitWall(false);
		}
		while(true) {
			wS = WumpusConstants.getDirectionInt(word);
		    Cell temp = null;
			switch(wS) {
		        case 0: case 4: case 8: case 12:
		        	this.setDirection(0); temp = cave.move(getCurrentX(), getCurrentY(),0); 
		        	if(temp != null) {
		        		this.setCurrentCell(temp);
		        		this.setCurrentX(this.getCurrentX() -1 );
		        	}
		        	break;
		        case 1: case 5: case 9: case 13:
		        	this.setDirection(1); temp = cave.move(getCurrentX(), getCurrentY(),1); 
		        	if(temp != null){
		        		this.setCurrentCell(temp);
		        		this.setCurrentX(this.getCurrentX() +1);
		        	}
		            break;
		        case 2: case 6:  case 10: case 14:
		        	this.setDirection(2); temp = cave.move(getCurrentX(), getCurrentY(),2);
		        	if(temp != null) {
		        		this.setCurrentCell(temp);
		        		this.setCurrentY(this.getCurrentY() +1);
		        	}
		        	break;
		        case 3: case 7: case 11: case 15:
		        	this.setDirection(3); temp = cave.move(getCurrentX(), getCurrentY(),3); 
		        	if(temp != null) {
		        		this.setCurrentCell(temp);
		        		this.setCurrentY(this.getCurrentY() -1);
		        	}
		        	break;
		        case -1: default:
		        	String s = this.askPlayer("Sorry, you didn't give me a direction. Do you want to move " +
		        			WumpusConstants.directionsLC[this.getDirection()] +  "? (Yes/No)").toLowerCase();
		        	if(s.startsWith("n")){
		        		word = this.askPlayer("Ok, give me a new direction or do nothing by giving me nothign.");
		        		if(word == null || word.equals("")) {
			        		System.out.println("You didn't move."); return false;
			        	}			        	
		        		if(word.toLowerCase().equals("nothing")){
			        		System.out.println("Oh you smartass... \nYou didn't move."); return false;
			        	}
			        	continue;
		        	} else if(s.startsWith("y")) {
		        		word = WumpusConstants.directionsLC[this.getDirection()]; continue; 
		        	} else word = "--"; continue;
		    }
			System.out.println("You moved " + WumpusConstants.directionsLC[this.getDirection()]);
			this.addScore(-1);
		    break;
		}
		return true;
	}
	
	public boolean grab() {
		this.addScore(-1);
		if(this.cave.performGrabGold(getCurrentX(), getCurrentY())){
			this.setHasTheGold(true);
			this.addScore(1000);
			System.out.print("You found the gold! ");
			return true;
		} else {
			System.out.println("No, the gold's not here, keep searching...");
			return false;
		}
	}
	
	/**
	 * Use this to analyze the line.
	 * @param line
	 */
	public void analyze(String line) {
		if (line == null) return;
		StringTokenizer st = new StringTokenizer(line);
		while(st.hasMoreTokens()) {
			String word = st.nextToken();
			int wordInt = WumpusConstants.getWordInt(word);
			
			switch(wordInt) {
			case 0: case 1: continue;
			case 2: case 6: case 10: case 11: turn(st); break;
			case 3: case 7: case 8: case 9:   move(st); break;
			case 4: if(grab()) return; else break;
			case 5: shoot(st); break;
			default: continue;
			}
			this.currentCell.printCell();
		}
		
	}
	
	public static void main(String[] args) {
		WumpusGame wg = new WumpusGame();
		wg.play();
	}
}
